package com.filestation.backend.controller;

import com.filestation.backend.entity.FileInfo;
import com.filestation.backend.model.FileUploadDTO;
import com.filestation.backend.model.Result;
import com.filestation.backend.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/files")
public class FileController {

    @Autowired
    private FileService fileService;
    
    @Value("${server.servlet.context-path}")
    private String contextPath;

    /**
     * 上传文件
     */
    @PostMapping("/upload")
    public Result<FileUploadDTO> uploadFile(
            @NotNull @RequestParam("file") MultipartFile file,
            @RequestParam(value = "expirationDays", defaultValue = "7") @Min(1) @Max(30) Integer expirationDays,
            @RequestParam(value = "description", required = false) String description,
            HttpServletRequest request) {
        
        if (file.isEmpty()) {
            return Result.error("上传文件不能为空");
        }
        
        try {
            FileInfo fileInfo = fileService.uploadFile(file, expirationDays, description, request);
            
            // 转换为DTO
            FileUploadDTO dto = new FileUploadDTO();
            dto.setOriginalFileName(fileInfo.getOriginalFileName());
            dto.setFileUrl(fileInfo.getFileUrl());
            dto.setDownloadCode(fileInfo.getDownloadCode());
            dto.setDownloadUrl(buildDownloadUrl(fileInfo.getDownloadCode()));
            dto.setFileSize(fileInfo.getFileSize());
            
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            dto.setExpirationTime(sdf.format(fileInfo.getExpirationTime()));
            
            return Result.success("文件上传成功", dto);
        } catch (Exception e) {
            log.error("文件上传失败", e);
            return Result.error("文件上传失败：" + e.getMessage());
        }
    }

    /**
     * 上传多个文件并压缩
     */
    @PostMapping("/upload/multiple")
    public Result<FileUploadDTO> uploadMultipleFiles(
            @NotNull @RequestParam("files") List<MultipartFile> files,
            @RequestParam(value = "zipName", required = false) String zipName,
            @RequestParam(value = "expirationDays", defaultValue = "7") @Min(1) @Max(30) Integer expirationDays,
            @RequestParam(value = "description", required = false) String description,
            HttpServletRequest request) {
        
        if (files.isEmpty()) {
            return Result.error("上传文件不能为空");
        }
        
        try {
            FileInfo fileInfo = fileService.uploadMultipleFiles(files, zipName, expirationDays, description, request);
            
            // 转换为DTO
            FileUploadDTO dto = new FileUploadDTO();
            dto.setOriginalFileName(fileInfo.getOriginalFileName());
            dto.setFileUrl(fileInfo.getFileUrl());
            dto.setDownloadCode(fileInfo.getDownloadCode());
            dto.setDownloadUrl(buildDownloadUrl(fileInfo.getDownloadCode()));
            dto.setFileSize(fileInfo.getFileSize());
            
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            dto.setExpirationTime(sdf.format(fileInfo.getExpirationTime()));
            
            return Result.success("文件上传成功", dto);
        } catch (Exception e) {
            log.error("文件上传失败", e);
            return Result.error("文件上传失败：" + e.getMessage());
        }
    }

    /**
     * 根据下载码下载文件
     */
    @GetMapping("/download/{downloadCode}")
    public ResponseEntity<UrlResource> downloadFile(@PathVariable String downloadCode) {
        try {
            FileInfo fileInfo = fileService.getFileByDownloadCode(downloadCode);
            
            // 增加下载次数
            fileService.incrementDownloadCount(fileInfo.getId());
            
            // 构建下载链接并进行重定向
            UrlResource resource = new UrlResource(fileInfo.getFileUrl());
            
            // 文件名编码，解决中文乱码问题
            String encodedFileName = URLEncoder.encode(fileInfo.getOriginalFileName(), StandardCharsets.UTF_8.toString())
                    .replaceAll("\\+", "%20");
            
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"")
                    .body(resource);
        } catch (Exception e) {
            log.error("文件下载失败", e);
            throw new RuntimeException("文件下载失败：" + e.getMessage());
        }
    }

    /**
     * 查询文件信息
     */
    @GetMapping("/info/{downloadCode}")
    public Result<FileInfo> getFileInfo(@PathVariable String downloadCode) {
        try {
            FileInfo fileInfo = fileService.getFileByDownloadCode(downloadCode);
            return Result.success(fileInfo);
        } catch (Exception e) {
            log.error("获取文件信息失败", e);
            return Result.error("获取文件信息失败：" + e.getMessage());
        }
    }

    /**
     * 获取所有文件列表
     */
    @GetMapping("/list")
    public Result<List<FileInfo>> listFiles() {
        try {
            List<FileInfo> files = fileService.getAllFiles();
            return Result.success(files);
        } catch (Exception e) {
            log.error("获取文件列表失败", e);
            return Result.error("获取文件列表失败：" + e.getMessage());
        }
    }

    /**
     * 删除文件
     */
    @DeleteMapping("/{fileKey}")
    public Result<Void> deleteFile(@PathVariable String fileKey) {
        try {
            boolean deleted = fileService.deleteFile(fileKey);
            if (deleted) {
                return Result.success("文件删除成功", null);
            } else {
                return Result.error("文件删除失败");
            }
        } catch (Exception e) {
            log.error("文件删除失败", e);
            return Result.error("文件删除失败：" + e.getMessage());
        }
    }
    
    /**
     * 构建下载URL
     */
    private String buildDownloadUrl(String downloadCode) {
        return contextPath + "/files/download/" + downloadCode;
    }
} 